<template>
    <div class="flex flex-col items-center w-full">
        <div class="doc-uploader">
            <div class="w-[740px] h-[280px] p-4 bg-body rounded-lg border border-br-light">
                <el-upload
                    ref="uploadRef"
                    v-model:file-list="fileList"
                    :headers="uploadParams.headers"
                    :action="uploadParams.action"
                    :accept="uploadParams.accept"
                    :data="{mode: promptCode}"
                    :limit="1"
                    :disabled="upLoading"
                    :multiple="false"
                    :show-file-list="false"
                    :before-upload="beforeUpload"
                    :on-progress="handleProgress"
                    :on-success="uploadSuccess"
                    :on-exceed="handleExceed"
                    :on-error="handleError"
                    drag
                    style=" height: 100%; background: unset;"
                >
                    <!-- 上传未开始 -->
                    <div v-if="fileList.length <= 0">
                        <div class="flex flex-col items-center mb-4">
                            <icon name="svg-icon-Upload" :size="48" color="var(--el-text-color-placeholder)" />
                            <span class="pt-4 font-bold text-xl text-tx-regular">
                                <span class="text-primary">点击上传</span>
                                <span class="ml-2">或拖拽到此处上传文档</span>
                            </span>
                        </div>
                        <div class="text-sm text-tx-secondary mb-4">
                            <span>当前支持 </span>
                            <span class="text-primary">PDF/DOC/DOCX/TXT/HTML/PPT/PPTX</span>
                        </div>
                        <div class="text-sm text-tx-secondary">暂不支持图片版/扫描版文档</div>
                    </div>

                    <!-- 上传进行中 -->
                    <div v-if="upLoading" >
                        <el-progress
                            v-if="!upSucceed && !upFailed"
                            type="circle"
                            :percentage="progress"
                            :width="117"
                        />
                        <div v-if="progress < 99" class="mt-3 text-primary text-base">正在上传中 ...</div>
                        <div v-if="progress === 99" class="mt-3 text-primary text-base">正在解析中 ...</div>
                    </div>

                    <!-- 上传已完成 -->
                    <transition name="fade">
                        <div v-if="upSucceed" class="h-full flex justify-center items-center text-success">
                            <icon name="el-icon-SuccessFilled" :size="24"/>
                            <span class="ml-1 text-xl font-medium">上传成功</span>
                        </div>
                        <div v-else-if="upFailed" class="h-full flex justify-center items-center text-error">
                            <icon name="el-icon-WarningFilled" :size="24"/>
                            <span class="ml-1 text-xl font-medium">上传失败，请重试</span>
                        </div>
                    </transition>
                </el-upload>
            </div>

            <div class="prompts grid grid-cols-3 gap-3 mt-6">
                <div
                    v-for="(item, index) in promptList"
                    :key="index"
                    class="prompt-item px-3 w-[238px] h-[80px] flex items-center bg-body rounded-lg"
                    :class="{ 'active': item.code === promptCode }"
                    @click="promptCode = item.code"
                >
                    <el-image
                        :src="item.icon"
                        class="shrink-0 w-[30px] h-[30px] rounded-sm"
                    />
                    <div class="flex-start ml-1.5">
                        <h3 class="font-bold text-base text-tx-regular">
                            {{ item.name }}
                        </h3>
                        <p class="h-[36px] mt-1.5 line-clamp-2 text-xs text-tx-placeholder">
                            {{ item.intro }}
                        </p>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import config from '~/config/index'
import useUserStore from '~/stores/user'
import { genFileId } from 'element-plus'
import docsFilesApi from '~/api/apply/docs/files'
import type {
    ElUpload,
    UploadFile,
    UploadProps,
    UploadRawFile,
    UploadUserFile,
    UploadProgressEvent
} from 'element-plus'

const emits = defineEmits<{
    (e: 'upload-success', v: any): void;
}>()

const userStore = useUserStore()

// 提示词组
const promptCode = ref<string>('')
const promptList = ref([] as DocFilesPromptsResponse[])

// 上传参数
const httpBase: string = config.baseUrl + config.urlPrefix
const uploadParams = ref({
    action: httpBase + '/apply/docs/files/upload',
    accept: '.pdf,.doc,.docx,.ppt,pptx,.txt,.md,.html',
    headers: {
        Authorization: 'Bearer ' + userStore.token,
        Terminal: config.terminal
    },
    data: {
        mode: promptCode.value
    }
})

// 文件信息
const progress = ref<number>(0)
const fileList = ref<UploadUserFile[]>([])
const uploadRef = ref<InstanceType<typeof ElUpload>>()

// 上传状态
const upLoading = ref<boolean>(false)
const upSucceed = ref<boolean>(false)
const upFailed = ref<boolean>(false)

/**
 * 上传之前限制
 *
 * @param {UploadRawFile} file
 * @author zero
 */
const beforeUpload = (file: UploadRawFile) => {
    if (!userStore.isLogin) {
        feedback.msgError('请先登录')
        return false
    }

    const ext = file.name.substring(file.name.lastIndexOf('.') + 1)
    if (uploadParams.value.accept) {
        const accepted = uploadParams.value.accept.split(',')
        if (!accepted.includes('.' + ext.toLowerCase())) {
            feedback.msgError('不被支持的文件')
            return false
        }
    }
    if (file.size > 1024 * 1024 * 15) {
        feedback.msgError('文件限制少于等于 15MB')
        return false
    }
    if (!promptCode.value) {
        feedback.msgError('请选择分析类型再上传文件')
        return false
    }
}

/**
 * 上传进度处理
 *
 * @param {UploadProgressEvent} evt
 * @author zero
 */
const handleProgress = (evt: UploadProgressEvent) => {
    upLoading.value = true
    if (evt.percent < 100) {
        progress.value = parseInt(String(evt.percent))
    }
}

/**
 * 上传成功处理
 *
 * @param response
 * @author zero
 */
const uploadSuccess = (response: any) => {
    if (progress.value === 0) {
        for (let i = 0; i < 99; i++) {
            progress.value += 1
        }
    }

    if (response.code === 0) {
        const code: string = response.data.code
        setTimeout(() => {
            upSucceed.value = true
            upFailed.value = false
            progress.value = 100
        }, 2000)
        setTimeout(() => {
            upLoading.value = false
            emits('upload-success', code)
        }, 3000)
    } else {
        feedback.msgError(response.msg)
        upLoading.value = false
        upSucceed.value = false
        upFailed.value = true
        progress.value = 0
    }
}

/**
 * 超出限制处理
 * 自动替换上1个文件
 *
 * @param {File[]} files
 * @author zero
 */
const handleExceed: UploadProps['onExceed'] = (files: File[]) => {
    upLoading.value = false
    upFailed.value = false
    upSucceed.value = false
    progress.value = 0
    const file = files[0] as UploadRawFile
    file.uid = genFileId()
    uploadRef.value!.clearFiles()
    uploadRef.value!.handleStart(file)
    uploadRef.value!.submit()
}

/**
 * 上传失败处理
 *
 * @param {Error} error
 * @param {UploadFile} file
 * @author zero
 */
const handleError = (error: Error, file: UploadFile) => {
    feedback.msgError(`${file.name} 上传失败: ${error.message}`)
    upLoading.value = false
    upSucceed.value = false
    upFailed.value = false
    progress.value = 0
    uploadRef.value?.abort(file)
}

onMounted(async () => {
    promptList.value = await docsFilesApi.prompts()
    if (promptList.value.length > 0) {
        promptCode.value = promptList.value[0].code
    }
})
</script>

<style scoped lang="scss">
.doc-uploader {
    :deep(.el-upload) {
        height: 100% !important;
        .el-upload-dragger {
            height: 100%;
            background-color: var(--el-bg-color);
        }
    }

    .prompts {
        .prompt-item {
            cursor: pointer;
            border: 1px solid var(--el-border-color-lighter);
            &:hover,
            &.active {
                border-color: var(--el-color-primary);
            }
        }
    }
}
</style>
